///////////////////////////////////////////////
///      Product Name: WordQuicker          ///
/// Copyright (c)2007, Marstone Studio      ///
///           Author: marstone              ///
///        Web Site: marstone.net           ///
///      Mail/MSN: marstone@163.com         ///
///         Created: 2007.09.25             ///
///      Last Modified: 2007.09.27          ///
///////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;
using Word = Microsoft.Office.Interop.Word;
using System.IO;

namespace Studio.Windows.WordQuicker
{

    public class WQApplicationClass : WQApplication
    {

        /// <summary>
        /// The Word Application
        /// </summary>
        private Word.ApplicationClass WordApplication = null;


        /// <summary>
        /// Construct the ApplicationClass Instance
        /// </summary>
        public WQApplicationClass()
        {
            WordApplication = new Word.ApplicationClass();
        }




        /// <summary>
        /// Construct the ApplicationClass Instance
        /// </summary>
        public WQApplicationClass(bool Visable, string Caption)
        {

            WordApplication = new Word.ApplicationClass();
            WordApplication.Caption = Caption;
            WordApplication.Visible = Visable;
            WordApplication.Options.CheckSpellingAsYouType = false;
            WordApplication.Options.CheckGrammarAsYouType = false;

        }



        public WQDocument OpenDocument(string FileName)
        {

            Word.Document WordDoc = null;

            Object filename = Path.GetFullPath(FileName);
            Object ConfirmConversions = false;
            Object ReadOnly = false;
            Object AddToRecentFiles = false;

            Object PasswordDocument = System.Type.Missing;
            Object PasswordTemplate = System.Type.Missing;
            Object Revert = System.Type.Missing;
            Object WritePasswordDocument = System.Type.Missing;
            Object WritePasswordTemplate = System.Type.Missing;
            Object Format = System.Type.Missing;
            Object Encoding = System.Type.Missing;
            Object Visible = false;
            Object OpenAndRepair = System.Type.Missing;
            Object DocumentDirection = System.Type.Missing;
            Object NoEncodingDialog = true;
            Object XMLTransform = System.Type.Missing;

            FileStream fs = null;

            try
            {
                // Set attribute to NOT readonly
                File.SetAttributes(FileName, File.GetAttributes(FileName) & ~FileAttributes.ReadOnly);

                // Test if the file CanWrite
                fs = new FileStream(FileName, FileMode.Open, FileAccess.Write);
                // In fact, if the file can not be writen, the upper sentence will cause a exception
                // so, what does the next sentense mean ?
                if (false == fs.CanWrite)
                {
                    Console.Write(FileName.ToString() + "can not be write.");
                    return null;
                }
                // Close
                fs.Close();
                fs = null;

                // Open it
                WordDoc = WordApplication.Documents.Open(ref filename, ref ConfirmConversions,
                        ref ReadOnly, ref AddToRecentFiles, ref PasswordDocument, ref PasswordTemplate,
                        ref Revert, ref WritePasswordDocument, ref WritePasswordTemplate, ref Format,
                        ref Encoding, ref Visible, ref OpenAndRepair, ref DocumentDirection,
                        ref NoEncodingDialog, ref XMLTransform);

                return new WQDocumentClass(WordDoc);
            }

            catch (Exception ex)
            {
                if (null != WordDoc) this.CloseDocument(false);
                if (null != WordDoc) System.Runtime.InteropServices.Marshal.ReleaseComObject(WordDoc);
                System.Console.WriteLine(ex.Message);
                return null;
            }
            finally
            {
                if (null != fs) fs.Close();
            }
        }

        /// <summary>
        /// Close & Save without prompt
        /// </summary>
        public void CloseDocument(bool Save)
        {
            // Closes all documents: saves with no prompt
            Object saveChanges = Save ? Word.WdSaveOptions.wdSaveChanges : Word.WdSaveOptions.wdDoNotSaveChanges;
            Object originalFormat = Type.Missing;
            Object routeDocument = Type.Missing;
            WordApplication.Documents.Close(ref saveChanges, ref originalFormat, ref routeDocument); 
        }

        public void QuitApplication(bool Save)
        {
            Object saveChanges = Save ? Word.WdSaveOptions.wdSaveChanges : Word.WdSaveOptions.wdDoNotSaveChanges;
            Object originalFormat = Type.Missing;
            Object routeDocument = Type.Missing;
            WordApplication.Quit(ref saveChanges, ref originalFormat, ref routeDocument);
            WordApplication = null;
        }

        /// <summary>
        /// Quit without Save
        /// </summary>
        public void QuitApplication()
        {
            QuitApplication(false);
        }

        /// <summary>
        /// End Application
        /// </summary>
        ~WQApplicationClass()
        {
            if (null != WordApplication)
                try
                {
                    QuitApplication();
                }
                catch
                { 
                    // Do nothing, bypass the error
                    // it always caused by the COM is already disconnected.
                }
        }


        // useless, who can tell me why ?
        public event WQApplicationQuitEventHandler ApplicationQuit
        {
            add
            {
                WordApplication.ApplicationEvents4_Event_Quit += new Word.ApplicationEvents4_QuitEventHandler(value);
            }
            remove
            {
                WordApplication.ApplicationEvents4_Event_Quit -= new Word.ApplicationEvents4_QuitEventHandler(value);
            }
        }

        /// <summary>
        /// Finilize resource, decrease reference and clear memory
        /// </summary>
        public void Dispose()
        {
            if (this.WordApplication != null)
            {
                QuitApplication();
                System.Runtime.InteropServices.Marshal.ReleaseComObject(this.WordApplication);
                this.WordApplication = null;
            }

            GC.Collect();
        }

    }
}
